package cn.biplam.front.component.data.tree;

import java.util.ArrayList;
import java.util.List;

import cn.biplam.common.bean.md.IndexTable;
import cn.biplam.common.client.DataFilter;
import cn.biplam.common.client.DbResource;
import cn.biplam.common.client.Operator;
import cn.biplam.common.client.OperatorResult;
import cn.biplam.common.opcode.SysManageCode.TreeIndexCode;
import cn.biplam.common.tools.TOOLS;
import cn.biplam.common.wrapper.ErrorMessage;
import cn.biplam.common.wrapper.KvMap;
import cn.biplam.common.wrapper.sqlresult.SqlResult;
import cn.biplam.common.wrapper.tree.TreeIndexFields;
import cn.biplam.common.wrapper.tree.TreeStructre;

/**
 * 	索引表为数据源的树形控件数据操作组件
 * @author XiaoRuxing 2009-6-8下午04:03:29
 * @version 1.0
 */
public class TreeIndexData extends TreeData{

	private SqlResult sr;
	private String tableName;
	/**向下取几级数据 */
	private String levelDown;
	private DataFilter filter;

	private String userID;
	private DbResource dbr;

	private TreeIndexFields fields;
	private boolean virtualNodeVisiable=false;

	/** 当前展开节点ID */
	private String curNodeId;
	/** 获取节点过滤列表操作ID */
	private String nodeFilterOperatorId;
	/** 节点过滤过滤器 */
	private DataFilter nodeFilter;

	/** 虚拟根节点名称来源,默认来自数据库 */
	private Virtual_Node_Name_From virtualNameFrom = Virtual_Node_Name_From.Db;
	/** 父亲们是否有弟弟 */
	private String parentsHaveLBrother;
	/**当前节点是否有弟弟 */
	private String haveLBrother;
	/**当前节点是否有哥哥 */
	private String haveBrother;
	/** 当前节点级别 */
	private String nodeLevel;
	

	public TreeIndexData(){
		this.filter=new DataFilter();
	}

	/**
	 * 设置索引表树形控件的数据源
	 * @param tableName   表名
	 * @param userID      用户ID
	 * @param nodeId      当前节点id
	 * @param nodeLevel   当前节点级别，当取根节点的时候 级别为0
	 * @param levelDown   向下取几级数据 -1 全部 0 当前  1 当前节点下1级 2当前节点向下2级 ... n当前节点向下n级
	 * @param nodeType    节点类型
	 * @param haveBrother 是否有哥哥
	 * @param haveLBrother 是否有弟弟
	 * @param parentsHaveLBrother 节点父亲们是否有弟弟
	 * @throws ErrorMessage  
	 * ?以当前节点为根，取子树的问题
	 */
	public void setData(String tableName,
			String userID,
			String nodeId,
			String nodeLevel,
			String levelDown,
			String nodeType,
			String haveBrother,
			String haveLBrother,
			String parentsHaveLBrother) throws ErrorMessage{
		this.setData(tableName, userID, nodeId,nodeLevel,levelDown,nodeType,haveBrother,
				haveLBrother,parentsHaveLBrother,new DbResource());
	}

	/**
	 * 设置索引表树形控件的数据源
	 * @param tableName   表名
	 * @param userID      用户ID
	 * @param nodeId      当前节点id
	 * @param nodeLevel   当前节点级别
	 * @param levelDown   向下取几级数据 -1 全部 0 当前  1 当前节点下1级 2当前节点向下2级 ... n当前节点向下n级
	 * @param nodeType    节点类型
	 * @param haveBrother 是否有哥哥
	 * @param haveLBrother 是否有弟弟
	 * @param parentsHaveLBrother 节点父亲们是否有弟弟
	 * @param dbr      数据操作数据源
	 * @throws ErrorMessage 
	 */
	public void setData(String tableName,
			String userID,
			String nodeId,
			String nodeLevel,
			String levelDown,
			String nodeType,
			String haveBrother,
			String haveLBrother,
			String parentsHaveLBrother,
			DbResource dbr) throws ErrorMessage{
		
		this.curNodeId = nodeId;
		this.fields=TreeIndexFields.getTreeFields(tableName);
		this.userID=userID;
		this.dbr=dbr;
		//设置查询树数据所需条件
		this.filter.put("table_name", tableName);               //表名称
		this.filter.put(fields.getNodeId(), nodeId);            //被展开节点
		this.filter.put("level_down", getDownLevel(levelDown)); //向下级别
		this.filter.put(fields.getNodeType(), nodeType);        //节点索引类型
		//被展开节点信息
		this.nodeLevel = nodeLevel;
		this.parentsHaveLBrother = parentsHaveLBrother;
		this.haveLBrother = haveLBrother;
		this.haveBrother = haveBrother;
		this.tableName=tableName;
		this.levelDown=levelDown;
	}

	/**
	 *  设置虚根节点是否显示
	 * @param virtualNodeVisialble
	 */
	public void setVirtualNodeVisiable(boolean virtualNodeVisialble){
		this.virtualNodeVisiable = virtualNodeVisialble;
	}

	/**
	 * 创建树数据
	 * @throws ErrorMessage 
	 */
	public void create() throws ErrorMessage {
		switch(TOOLS.stringToInt(this.levelDown)){
		case 0://获取单个节点
			sr=Operator.get(TreeIndexCode.Select_Flat_Node, this.userID, filter, this.dbr).getSelectResult();
			this.SqlResultToArray();
			break;
		default:
			if(TOOLS.stringToInt(this.levelDown)>-2){
				getTreeData();
			}else{
				throw new ErrorMessage("TreeIndexData levelDown is not found"+this.levelDown+"!");
			}
		}
		this._setVirtualNode();
	}

	/**
	 *  设置获取叶子节点过滤列表操作ID<BR>
	 *  operator操作的参数名称和值为: 过滤条件的默认参数oid(当前节点ID),NODE_CODE(节点真实ID)
	 * @param operatorId 操作ID
	 */
	public void setFilterOperator(String operatorId){
		this.setFilterOperator(operatorId, null);
	}
	
	/**
	 *  设置获取叶子节点过滤列表操作ID<BR>
	 *  operator操作的参数名称和值为: 过滤条件的默认参数oid(当前节点ID),NODE_CODE(节点真实ID)
	 * @param operatorId 操作ID
	 * @param nodeFilter 节点过滤条件
	 */
	public void setFilterOperator(String operatorId,DataFilter nodeFilter){
		this.nodeFilterOperatorId = operatorId;
		this.nodeFilter = nodeFilter;
	}

	/**
	 *  设置虚拟根节点描述信息来源类型（外面设置或数据库读取）(默认来自数据库,如果数据库读取的信息为空则来自于外面)
	 * @param type 描述信息来源类型(Virtual_Node_Name_From)
	 */
	public void setVirtualInfoFrom(Virtual_Node_Name_From type){
		if(type==null)return;
		this.virtualNameFrom = type;
	}

	/**
	 * 取得需展开节点的所有父亲id
	 * @param extendNodeId 需要展开的节点Id
	 * @param level        需要展开的节点在树中的级别
	 * @return KvMap<父节点id,父节点id>
	 * @throws ErrorMessage 
	 */
	@Override
	public KvMap<String, String> getExtendNodeAllParent(String extendNodeId) throws ErrorMessage {
		KvMap<String, String> kvParents = null;
		DataFilter filter=new DataFilter();
		filter.put("table_name", tableName);
		filter.put(this.fields.getNodeId(), extendNodeId);
		OperatorResult rs=Operator.get(TreeIndexCode.Select_Node_Parents, 
				this.userID, filter,this.dbr);
		if(rs!=null){
			kvParents = rs.getKvResult();
		}
		return kvParents;
	}

	/**
	 *  获取从数据库读取索引数据时向下获取数据的级数
	 *  如果向下展开级数为-1(展开全部),0(展开本级)不处理
	 *  N(展开N级) 获取数据时多向下获取一级
	 * @return
	 */
	private String getDownLevel(String downLevel){
		if(TOOLS.stringToInt(downLevel)<1){
			return downLevel;
		}else{
			return String.valueOf(TOOLS.stringToInt(downLevel)+1);
		}
	}

	/**
	 *  获取树数据
	 */
	private void getTreeData() throws ErrorMessage{
		//从数据库查询当前子树的所有数据
		OperatorResult treeData =Operator.get(TreeIndexCode.Select_Sub_Tree, this.userID, filter, this.dbr);
		SqlResult filterResult = getDataAfterFilter(treeData);//过滤后数据
		//放入链表结构生成绘制树的所需标示字段
		TreeStructre tree=TreeIndexFields.bindTreeDataToLinkList(filterResult, 
				fields, 
				this.curNodeId, 
				this.nodeLevel, 
				this.haveBrother, 
				this.haveLBrother, 
				this.parentsHaveLBrother);
		if(tree!=null){
			this.rs = tree.getChildren(this.curNodeId,this.levelDown);
		}
	}

	/**
	 *  获取过滤后的数数据
	 * @throws ErrorMessage 
	 */
	private SqlResult getDataAfterFilter(OperatorResult result) throws ErrorMessage{
		//获取过滤节点列表
		List<String> filterList = getFilterList();
		//删除被过滤的节点
		SqlResult selectResult= result.getSelectResult();
		if(filterList == null || selectResult==null){
			return selectResult;
		}
		for(String filterNode: filterList){
			DataFilter deleteCondition = new DataFilter();
			deleteCondition.put(this.fields.getNodeId(), filterNode);
			selectResult.delete(deleteCondition);
		}
		return selectResult;
	}

	/**
	 * @return 获取树节点过滤列表,只过滤叶子节点
	 * @throws ErrorMessage
	 */
	private List<String> getFilterList() throws ErrorMessage{
		if(this.nodeFilterOperatorId==null
				||"null".equals(nodeFilterOperatorId) //当过滤操作为空时ajxGet方法传入的的标示为字符串"null"
		)return null;//如果未设置过滤返回
		//过滤条件
		DataFilter filter = null;
		if(this.nodeFilter==null){
			filter = new DataFilter(this.curNodeId);
		}else{
			filter = this.nodeFilter;
			filter.put(this.curNodeId);
		}
		filter.put(this.fields.getRealId(), getNodeRealId(this.curNodeId));
		//根据传入的过滤列表操作ID获取过滤列表
		OperatorResult filterRs = Operator.get(this.nodeFilterOperatorId, this.userID, filter, this.dbr);
		
		List<String> filterList = null;
		String fiterNodeId = null;     //过滤节点ID
		if(TOOLS.exist(filterRs)){
			filterList = new ArrayList<String>();
			do{
				fiterNodeId = filterRs.getValue(this.fields.getNodeId());
				filterList.add(fiterNodeId);
			}while(filterRs.next());
		}
		//返回过滤节点列表
		return filterList;
	}

	/**
	 *  获取节点真实ID
	 */
	private String getNodeRealId(String nodeId) throws ErrorMessage{
		IndexTable index = IndexTable.getNewInstance(this.userID, this.tableName, nodeId);
		return index.getNodeCode();
	}

	/**
	 * 将数据集转换成二维数组 
	 */
	private void SqlResultToArray() throws ErrorMessage{
		this.rs = sr.getArray();
	}

	/**
	 *  设置虚根节点数据
	 * @throws ErrorMessage
	 */
	private void _setVirtualNode() throws ErrorMessage{
		if(this.virtualNodeVisiable){
			OperatorResult nodeInfo = Operator.get(TreeIndexCode.Select_Node, this.userID, filter);
			if(TOOLS.exist(nodeInfo)){ //虚拟根节点在表中存在
				String virturalNode = nodeInfo.getValue(fields.getNodeName()); 
				if(!TOOLS.StringIsEmpty(virturalNode)//虚拟根节点名称不为空
						&& virtualNameFrom.equals(Virtual_Node_Name_From.Db)//内容标识位为来自数据库
				){ 
					this.setVirtualRootNode(virturalNode, vNodePic); //设置虚拟根节点
				}
			}
		}
	}

}
